﻿// ---------------------------------------------------------------------------------------------------------------------
//   Copyright (c) SRT Solutions 2009. All rights reserved.
// ---------------------------------------------------------------------------------------------------------------------

using System;
using System.Linq;

using NUnit.Framework;

using SRTSolutions.Elevate;

namespace SRTSolutions.Elevate.Guide
{
    public class Tuples
    {
        [Test]
        public void CreatingATuple()
        {
            //given two values
            var one = 1;
            var two = 2;

            //we can create a tuple
            Tuple<int, int> tuple = new Tuple<int, int>(one, two);

            Assert.AreEqual(1, tuple.First);
            Assert.AreEqual(2, tuple.Second);
        }

        [Test]
        public void CreatingATupleInferred()
        {
            //given two values
            var one = 1;
            var two = 2;

            //we can create a tuple without having to explicitly type out the type parameters like this
            var tuple = Tuple.Create(one, two);

            Assert.AreEqual(1, tuple.First);
            Assert.AreEqual(2, tuple.Second);
        }

        [Test]
        public void WorkingWithTuplesInMethods()
        {
            //given a sequence of tuples
            var tuples = Seq.Build(Tuple.Create("Billy", 10), Tuple.Create("Sam", 2), Tuple.Create("Julie", 5), Tuple.Create("Shannon", 12));

            //we can more easily work with tuples by deconstructing them
            //and assigning them useful names
            var averageAge =
                tuples
                .Average(tuple => tuple.Select((name, age) => age));

            Assert.AreEqual(7.25, averageAge);
        }

        #region Unit Tests

        [Test]
        public void ComparingTuplesEqualsMethod()
        {
            var one = Tuple.Create("alpha", "beta");
            var two = Tuple.Create("alpha", "beta");

            var result = one.Equals(two);

            Assert.IsTrue(result);
        }

        [Test]
        public void ComparingTuplesEqualsMethodFirstNotEqual()
        {
            var one = Tuple.Create("alpha", "beta");
            var two = Tuple.Create("gamma", "beta");

            var result = one.Equals(two);

            Assert.IsFalse(result);
        }

        [Test]
        public void ComparingTuplesEqualsMethodSecondNotEqual()
        {
            var one = Tuple.Create("alpha", "beta");
            var two = Tuple.Create("aplha", "gamma");

            var result = one.Equals(two);

            Assert.IsFalse(result);
        }

        [Test]
        public void ComparingTuplesEqualsOperator()
        {
            var one = Tuple.Create("alpha", "beta");
            var two = Tuple.Create("alpha", "beta");

            var result = one == two;

            Assert.IsTrue(result);
        }

        [Test]
        public void ComparingTuplesNotEqualsOperator()
        {
            var one = Tuple.Create("alpha", "beta");
            var two = Tuple.Create("alpha", "beta");

            var result = one != two;

            Assert.IsFalse(result);
        }

        [Test]
        public void ComparingTuplesEqualsOperatorFirstNotEqual()
        {
            var one = Tuple.Create("alpha", "beta");
            var two = Tuple.Create("gamma", "gamma");

            var result = one == two;

            Assert.IsFalse(result);
        }

        [Test]
        public void ComparingTuplesNotEqualsOperatorFirstNotEqual()
        {
            var one = Tuple.Create("alpha", "beta");
            var two = Tuple.Create("gamma", "beta");

            var result = one != two;

            Assert.IsTrue(result);
        }

        [Test]
        public void ComparingTuplesEqualsOperatorSecondNotEqual()
        {
            var one = Tuple.Create("alpha", "beta");
            var two = Tuple.Create("alpha", "gamma");

            var result = one == two;

            Assert.IsFalse(result);
        }

        [Test]
        public void ComparingTuplesNotEqualsOperatorSecondNotEqual()
        {
            var one = Tuple.Create("alpha", "beta");
            var two = Tuple.Create("alpha", "gamma");

            var result = one != two;

            Assert.IsTrue(result);
        }

        [Test]
        public void SelectArgumentException()
        {
            var tuple = Tuple.Create(1, 2);
            Func<int, int, int> tmp = null;
            Assert.Throws<ArgumentNullException>(() => tuple.Select(tmp));
        }

        #endregion
    }
}
